package com.ssy.lingxi.order.serviceimpl.web;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.MemberAndRoleIdDTO;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.common.utils.DateTimeUtil;
import com.ssy.lingxi.member.merchant.api.feign.inner.MemberInnerControllerFeign;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberRelationFeignVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.response.MemberFeignQueryVO;
import com.ssy.lingxi.order.entity.*;
import com.ssy.lingxi.order.model.bo.LogisticsAddressBO;
import com.ssy.lingxi.order.model.constant.*;
import com.ssy.lingxi.order.model.vo.basic.request.*;
import com.ssy.lingxi.order.model.vo.basic.response.DeliveryOrderDetailVO;
import com.ssy.lingxi.order.model.vo.basic.response.DeliveryOrderProductQueryVO;
import com.ssy.lingxi.order.model.vo.basic.response.DeliveryOrderQueryVO;
import com.ssy.lingxi.order.model.vo.common.request.LogisticsAddressVO;
import com.ssy.lingxi.order.repository.DeliveryOrderProductRepository;
import com.ssy.lingxi.order.repository.DeliveryOrderRepository;
import com.ssy.lingxi.order.repository.OrderRepository;
import com.ssy.lingxi.order.service.base.IBaseCacheService;
import com.ssy.lingxi.order.service.base.IBaseDeliveryHistoryService;
import com.ssy.lingxi.order.service.base.IBaseOrderDeliveryService;
import com.ssy.lingxi.order.service.web.IDeliveryOrderService;
import com.ssy.lingxi.order.service.web.IDeliveryPlanService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 送货计划相关接口实现类
 * @author czh
 * @version 2.0.0
 * @date 2021-07-20
 */
@Slf4j
@Service
public class DeliveryOrderServiceImpl implements IDeliveryOrderService {

    @Resource
    private IBaseCacheService baseCacheService;

    @Resource
    private JPAQueryFactory jpaQueryFactory;

    @Resource
    private DeliveryOrderRepository deliveryOrderRepository;

    @Resource
    private DeliveryOrderProductRepository deliveryOrderProductRepository;

    @Resource
    private IBaseDeliveryHistoryService historyService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private IDeliveryPlanService deliveryPlanService;

    @Resource
    private OrderRepository orderRepository;

    @Resource
    private IBaseOrderDeliveryService baseOrderDeliveryService;

    @Resource
    private MemberInnerControllerFeign memberInnerControllerFeign;

    /**
     * 查询会员名称
     * @param memberId
     * @param roleId
     * @param vendorMemberId
     * @param vendorRoleId
     * @param type 1=b2b; 2=srm
     * @return
     */
    private String getSubMemberName(Long memberId,Long roleId,Long vendorMemberId,Long vendorRoleId,Integer type){
        MemberRelationFeignVO memberFeignIdVO = new MemberRelationFeignVO();
        if(DeliveryOrderTypeStatusEnum.SRM.getCode().equals(type)) {
            memberFeignIdVO.setMemberId(memberId);
            memberFeignIdVO.setRoleId(roleId);
            memberFeignIdVO.setUpperMemberId(vendorMemberId);
            memberFeignIdVO.setUpperRoleId(vendorRoleId);
        }else{
            memberFeignIdVO.setMemberId(vendorMemberId);
            memberFeignIdVO.setRoleId(vendorRoleId);
            memberFeignIdVO.setUpperMemberId(memberId);
            memberFeignIdVO.setUpperRoleId(roleId);
        }
        Wrapper<MemberFeignQueryVO> memberRegisterInfo = memberInnerControllerFeign.getMemberInfo(memberFeignIdVO);
        if (memberRegisterInfo.getCode() == ResponseCode.SUCCESS.getCode() && memberRegisterInfo.getData() != null) {
            return DeliveryOrderTypeStatusEnum.SRM.getCode().equals(type)?memberRegisterInfo.getData().getMemberName():memberRegisterInfo.getData().getSubMemberName();
        }else{
            throw new BusinessException(memberRegisterInfo.getCode(),memberRegisterInfo.getMessage());
        }
    }

    private PageData<DeliveryOrderQueryVO> pageBase(MemberAndRoleIdDTO vendor,MemberAndRoleIdDTO buyer, DeliveryOrderPageVO pageVO, DeliveryOrderTypeStatusEnum type) {

        QDeliveryOrderDO deliveryOrderDO = QDeliveryOrderDO.deliveryOrderDO;
        JPAQuery<DeliveryOrderQueryVO> query = jpaQueryFactory
                .select(Projections.constructor(DeliveryOrderQueryVO.class, deliveryOrderDO.id, deliveryOrderDO.deliveryNo, deliveryOrderDO.digest, deliveryOrderDO.deliveryTime, deliveryOrderDO.vendorMemberName, deliveryOrderDO.buyerMemberName, deliveryOrderDO.createTime, deliveryOrderDO.outerStatus))
                .from(deliveryOrderDO);
        //供应商信息
        if(vendor!=null) {
            query.where(deliveryOrderDO.vendorMemberId.eq(vendor.getMemberId()).and(deliveryOrderDO.vendorRoleId.eq(vendor.getRoleId())));
            //会员名称
            if(!StringUtils.isEmpty(pageVO.getBuyerMemberName())) {
                query.where(deliveryOrderDO.buyerMemberName.like("%" + pageVO.getBuyerMemberName().trim() + "%"));
            }
        }
        //采购商
        if(buyer!=null) {
            query.where(deliveryOrderDO.buyerMemberId.eq(buyer.getMemberId()).and(deliveryOrderDO.buyerRoleId.eq(buyer.getRoleId())));
            //会员名称
            if(!StringUtils.isEmpty(pageVO.getBuyerMemberName())) {
                query.where(deliveryOrderDO.vendorMemberName.like("%" + pageVO.getBuyerMemberName().trim() + "%"));
            }
        }
        //通知单号
        if(!StringUtils.isEmpty(pageVO.getDeliveryNo())) {
            query.where(deliveryOrderDO.deliveryNo.like("%" + pageVO.getDeliveryNo().trim() + "%"));
        }
        if(type!=null){
            query.where(deliveryOrderDO.type.eq(type.getCode()));
        }

        //摘要
        if(!StringUtils.isEmpty(pageVO.getDigest())) {
            query.where(deliveryOrderDO.digest.like("%" + pageVO.getDigest().trim() + "%"));
        }

        //起始时间
        if(!StringUtils.isEmpty(pageVO.getStartDate())) {
            query.where(deliveryOrderDO.deliveryTime.goe(LocalDateTime.parse(pageVO.getStartDate().concat(" 00:00:00"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
        }

        //结束时间
        if(!StringUtils.isEmpty(pageVO.getEndDate())) {
            query.where(deliveryOrderDO.deliveryTime.loe(LocalDateTime.parse(pageVO.getEndDate().concat(" 23:59:59"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
        }
        //倒序排序、分页、总数
        query.orderBy(deliveryOrderDO.deliveryTime.desc(),deliveryOrderDO.createTime.desc());
        query.limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset());
        long totalCount = query.fetchCount();
        return new PageData<>(totalCount, query.fetch());
    }

    @Override
    public Wrapper<PageData<DeliveryOrderQueryVO>> pageBySRM(HttpHeaders headers, DeliveryOrderPageVO pageVO) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        return Wrapper.success(pageBase(new MemberAndRoleIdDTO(loginUser.getMemberId(),loginUser.getMemberRoleId()),null,pageVO,DeliveryOrderTypeStatusEnum.SRM));
    }

    @Override
    public Wrapper<PageData<DeliveryOrderQueryVO>> pageByB2B(HttpHeaders headers, DeliveryOrderPageVO pageVO) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        return Wrapper.success(pageBase(new MemberAndRoleIdDTO(loginUser.getMemberId(),loginUser.getMemberRoleId()),null,pageVO,DeliveryOrderTypeStatusEnum.B2B));
    }

    private boolean isMemberData(UserLoginCacheDTO loginUser, DeliveryOrderDO deliveryOrderDO){
        if(loginUser==null||deliveryOrderDO==null){return false;}
        return (deliveryOrderDO.getVendorMemberId().equals(loginUser.getMemberId())&&deliveryOrderDO.getVendorRoleId().equals(loginUser.getMemberRoleId()))
        ||(deliveryOrderDO.getBuyerMemberId().equals(loginUser.getMemberId())&&deliveryOrderDO.getBuyerRoleId().equals(loginUser.getMemberRoleId()));
    }

    private boolean isCreator(UserLoginCacheDTO loginUser, DeliveryOrderDO deliveryOrderDO){
        if(loginUser==null||deliveryOrderDO==null){return false;}
        return (deliveryOrderDO.getVendorMemberId().equals(loginUser.getMemberId())&&deliveryOrderDO.getVendorRoleId().equals(loginUser.getMemberRoleId()));
    }

    @Override
    public Wrapper<PageData<DeliveryOrderProductQueryVO>> pageProducts(HttpHeaders headers, DeliveryOrderProductPageVO pageVO) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        //查询送货单
        DeliveryOrderDO deliveryOrderDO = deliveryOrderRepository.findById(pageVO.getId()).orElse(null);
        if(deliveryOrderDO==null||!isMemberData(loginUser,deliveryOrderDO)){
            return Wrapper.success(new PageData<>(0L, Collections.emptyList()));
        }
        QDeliveryOrderProductDO qOrderProduct = QDeliveryOrderProductDO.deliveryOrderProductDO;
        JPAQuery<DeliveryOrderProductQueryVO> query = jpaQueryFactory
                .select(Projections.constructor(DeliveryOrderProductQueryVO.class,qOrderProduct.id,qOrderProduct.skuId,qOrderProduct.productName,qOrderProduct.orderNo,qOrderProduct.createTime,qOrderProduct.type,qOrderProduct.category,qOrderProduct.brand,qOrderProduct.unit,qOrderProduct.purchaseCount,qOrderProduct.deliveryCount))
                .from(qOrderProduct)
                .where(qOrderProduct.deliveryOrder.id.eq(pageVO.getId()));
        long totalCount = query.fetchCount();
        List<DeliveryOrderProductQueryVO> fetch = query.limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset()).fetch();
        return Wrapper.success(new PageData<>(totalCount, fetch));
    }

    private LogisticsAddressBO buildLogisticsAddressBO(LogisticsAddressVO param){
        if(param==null){
            return null;
        }
        LogisticsAddressBO addressBO=new LogisticsAddressBO();
        addressBO.setConsignee(param.getConsignee());
        addressBO.setProvinceName(param.getProvinceName());
        addressBO.setCityName(param.getCityName());
        addressBO.setDistrictName(param.getDistrictName());
        addressBO.setStreetName(param.getStreetName());
        addressBO.setAddress(param.getAddress());
        addressBO.setPhone(param.getPhone());
        addressBO.setCarNumbers(param.getCarNumbers());
        return addressBO;
    }

    private LogisticsAddressVO convertLogisticsAddressVO(LogisticsAddressBO param){
        LogisticsAddressVO addressVO=new LogisticsAddressVO();
        addressVO.setConsignee(param.getConsignee());
        addressVO.setProvinceName(param.getProvinceName());
        addressVO.setCityName(param.getCityName());
        addressVO.setDistrictName(param.getDistrictName());
        addressVO.setStreetName(param.getStreetName());
        addressVO.setAddress(param.getAddress());
        addressVO.setPhone(param.getPhone());
        addressVO.setCarNumbers(param.getCarNumbers());
        return addressVO;
    }

    private String createOrderSn(String orderSn) {
        String currentTimeOrderSn = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String orderSnKey = orderSn + currentTimeOrderSn;
        //订单号后面6位随机数
        String orderSnSuffix = stringRedisTemplate.opsForValue().get(orderSnKey);
        if (StringUtils.isEmpty(orderSnSuffix)){
            orderSnSuffix = "00001";
        }else {
            orderSnSuffix =String.format("%05d",Long.parseLong(orderSnSuffix) + 1L);
        }
        stringRedisTemplate.opsForValue().set(orderSnKey,orderSnSuffix,24 * 60 * 60 * 1000L, TimeUnit.MILLISECONDS);
        return orderSnKey+orderSnSuffix;
    }

    //收货地址构建
    private LogisticsAddressBO buildLogisticsAddressBO(Integer sourceType,String sourceNo,String orderNo,Long orderProductId){
        LogisticsAddressBO bo=new LogisticsAddressBO();
        if(DeliveryOrderSourceTypeEnum.isRelationOrder(sourceType)){
            //送货计划或送货通知单
            LogisticsAddressVO consignee = deliveryPlanService.getReceiveAddressBySourceNoOrOrderProductId(sourceNo, sourceType, orderProductId);
            BeanUtils.copyProperties(consignee,bo);
        }else if(DeliveryOrderSourceTypeEnum.MANUAL_ADD.getCode().equals(sourceType)){
            //手工录入
            OrderDO firstByOrderNo = orderRepository.findFirstByOrderNo(orderNo);
            if(firstByOrderNo==null){
                throw new BusinessException(ResponseCode.ORDER_DOES_NOT_EXIST);
            }
            OrderConsigneeDO consignee = firstByOrderNo.getConsignee();
            if(consignee!=null) {
                BeanUtils.copyProperties(consignee,bo);
            }
        }
        return bo;
    }

    private void convertDeliveryOrderDO(DeliveryOrderDO order,DeliveryOrderCreateVO param,Integer type){
        order.setType(type);
        order.setSourceType(param.getSourceType());
        order.setSourceNo(param.getSourceNo());
        order.setBuyerMemberId(param.getBuyerMemberId());
        order.setBuyerRoleId(param.getBuyerRoleId());
        order.setBuyerMemberName(getSubMemberName(order.getVendorMemberId(), order.getVendorRoleId(),param.getBuyerMemberId(), param.getBuyerRoleId(),type));
        order.setRemark(param.getRemark());
        order.setDigest(param.getDigest());
        order.setDeliveryTime(LocalDateTime.parse(param.getDeliveryTime().concat(" 00:00:00"),OrderServiceContants.DEFAULT_TIME_FORMATTER));
        order.setDeliveryStartTime(param.getDeliveryStartTime());
        order.setDeliveryEndTime(param.getDeliveryEndTime());
        order.setSendTime(LocalDateTime.parse(param.getSendTime(),OrderServiceContants.DEFAULT_TIME_FORMATTER));
        //送货地址
        LogisticsAddressBO logisticsAddressBO = buildLogisticsAddressBO(param.getDeliveryVO());
        if(logisticsAddressBO!=null) {
            order.setDeliverBO(logisticsAddressBO);
        }
        //收货地址
        DeliveryOrderProductParamVO firstProductVO = param.getProducts().get(0);
        LogisticsAddressBO receiveVO = buildLogisticsAddressBO(param.getSourceType(), param.getSourceNo(), firstProductVO.getOrderNo(),firstProductVO.getOrderProductId());
        order.setReceiverBO(receiveVO);
        /*
        LogisticsAddressBO receiveVO = buildLogisticsAddressBO(param.getReceiveVO());
        if(receiveVO!=null) {
            order.setReceiverBO(receiveVO);
        }*/

        //送货执行人
        LogisticsAddressBO executeVO = buildLogisticsAddressBO(param.getExecutorVO());
        if(executeVO!=null) {
            order.setExecutorBO(executeVO);
        }
        order.setOuterStatus(DeliveryOrderOuterStatusEnum.ALREADY_SUBMIT.getCode());
        //物流信息
        order.setDeliveryType(param.getSourceType());
        order.setLogisticsCompanyId(param.getLogisticsCompanyId());
        order.setLogisticsCompany(param.getLogisticsCompany());
        order.setLogisticsNo(param.getLogisticsNo());
        order.setUpdateTime(LocalDateTime.now());
    }

    private void convertDeliveryOrderDOByUpdate(DeliveryOrderDO order,DeliveryOrderUpdateVO param){
        order.setRemark(param.getRemark());
        order.setDigest(param.getDigest());
        //仅手工单可修改送货日期
        if(order.getSourceType().equals(DeliveryOrderSourceTypeEnum.MANUAL_ADD.getCode())) {
            order.setDeliveryTime(LocalDateTime.parse(param.getDeliveryTime().concat(" 00:00:00"), OrderServiceContants.DEFAULT_TIME_FORMATTER));
        }
        order.setDeliveryStartTime(param.getDeliveryStartTime());
        order.setDeliveryEndTime(param.getDeliveryEndTime());
        order.setSendTime(LocalDateTime.parse(param.getSendTime(),OrderServiceContants.DEFAULT_TIME_FORMATTER));
        //送货地址
        LogisticsAddressBO logisticsAddressBO = buildLogisticsAddressBO(param.getDeliveryVO());
        if(logisticsAddressBO!=null) {
            order.setDeliverBO(logisticsAddressBO);
        }
        //送货执行人
        LogisticsAddressBO executeVO = buildLogisticsAddressBO(param.getExecutorVO());
        if(executeVO!=null) {
            order.setExecutorBO(executeVO);
        }
        //物流信息
        order.setDeliveryType(param.getDeliveryType());
        order.setLogisticsCompanyId(param.getLogisticsCompanyId());
        order.setLogisticsCompany(param.getLogisticsCompany());
        order.setLogisticsNo(param.getLogisticsNo());
        order.setUpdateTime(LocalDateTime.now());
    }

    private List<DeliveryOrderProductDO> convertDeliveryOrderProductDOList(DeliveryOrderCreateVO param,DeliveryOrderDO order){
        List<DeliveryOrderProductParamVO> products = param.getProducts();
        int size = products.stream().collect(Collectors.groupingBy(DeliveryOrderProductParamVO::getOrderProductId)).size();
        if(size!=products.size()){
            throw new BusinessException(ResponseCode.ORDER_DELIVERY_ORDER_PRODUCT_REPEAT);
        }
        return products.stream().map(product -> {
            DeliveryOrderProductDO deliveryNoticeProductDO = new DeliveryOrderProductDO();
            deliveryNoticeProductDO.setDeliveryOrder(order);
            deliveryNoticeProductDO.setSkuId(product.getSkuId());
            deliveryNoticeProductDO.setProductName(product.getProductName());
            deliveryNoticeProductDO.setType(product.getSpec());
            deliveryNoticeProductDO.setCategory(product.getCategory());
            deliveryNoticeProductDO.setBrand(product.getBrand());
            deliveryNoticeProductDO.setUnit(product.getUnit());
            deliveryNoticeProductDO.setOrderNo(product.getOrderNo());
            deliveryNoticeProductDO.setCreateTime(LocalDateTime.parse(product.getCreateTime(),OrderServiceContants.DEFAULT_TIME_FORMATTER));
            deliveryNoticeProductDO.setPurchaseCount(product.getPurchaseCount());
            //缺少送货数量校验
            deliveryNoticeProductDO.setDeliveryCount(product.getDeliveryCount());
            deliveryNoticeProductDO.setOrderProductId(product.getOrderProductId());
            return deliveryNoticeProductDO;
        }).collect(Collectors.toList());
    }

    /**
     * 更新送货计划/送货通知单的数量信息
     * @param loginUser
     * @param order
     * @param statusEnum
     */
    private void updateRelationOrder(UserLoginCacheDTO loginUser,DeliveryOrderDO order,DeliveryOrderOuterStatusEnum statusEnum){
        if(DeliveryOrderSourceTypeEnum.DELIVERY_PLAN.getCode().equals(order.getSourceType())){
            //送货计划
            deliveryPlanService.updateDeliveryPlanStatus(loginUser,order,statusEnum.getCode());
        }else if(DeliveryOrderSourceTypeEnum.NOTICE_ORDER.getCode().equals(order.getSourceType())){
            //送货通知单
            deliveryPlanService.updateNoticeOrderStatus(loginUser,order,statusEnum.getCode());
        }
    }


    /**
     * 判断计划单或通知单是否重复
     * @param sourceType
     * @param sourceNo
     * @param deliveryDate
     * @param orderProductIds
     * @return
     */
    private Boolean existsRepeatRecord(Integer sourceType,String sourceNo,String deliveryDate,List<Long> orderProductIds){
        Specification<DeliveryOrderDO> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("sourceType").as(Integer.class), sourceType));
            list.add(criteriaBuilder.equal(root.get("sourceNo").as(String.class), sourceNo));
            list.add(criteriaBuilder.equal(root.get("deliveryTime").as(LocalDateTime.class), LocalDateTime.parse(deliveryDate.concat(" 00:00:00"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            Join<DeliveryOrderDO, DeliveryOrderProductDO> productDOJoin = root.join("deliveryOrderProductDOS", JoinType.LEFT);
            list.add(criteriaBuilder.in(productDOJoin.get("orderProductId")).value(orderProductIds));
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };
        List<DeliveryOrderDO> deliveryOrderDOS = deliveryOrderRepository.findAll(specification);
        boolean result = deliveryOrderDOS.size() > 0;
        if(result){
            log.warn("送货单：送货通知/计划重复提交了,sourceType:{},sourceNo:{},deliveryDate:{},orderProductId:{}",sourceType,sourceNo,deliveryDate,JSONUtil.toJsonStr(deliveryOrderDOS.stream().flatMap(o->o.getDeliveryOrderProductDOS().stream().map(p->p.getOrderProductId())).collect(Collectors.toList())));
        }
        return result;
    }

    @Transactional
    @Override
    public Wrapper<Void> createDeliveryOrder(HttpHeaders headers, DeliveryOrderCreateVO param, Integer type) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        //缺少校验商品、物料地址校验
        if(DeliveryOrderSourceTypeEnum.find(param.getSourceType())==null){
            return Wrapper.fail(ResponseCode.PARAM_NOT_EXIST);
        }else if(DeliveryOrderSourceTypeEnum.isRelationOrder(param.getSourceType())){
            if(!org.springframework.util.StringUtils.hasLength(param.getSourceNo())){
                return Wrapper.fail(ResponseCode.ORDER_DELIVERY_PLAN_NOTICE_IS_REQUIRED);
            }
            //如果是关联送货计划或送货通知，校验是否重复
            if(existsRepeatRecord(param.getSourceType(),param.getSourceNo(),param.getDeliveryTime(),param.getProducts().stream().map(o ->o.getOrderProductId()).collect(Collectors.toList()))){
                return Wrapper.fail(ResponseCode.ORDER_DELIVERY_ORDER_IS_REPEAT);
            }
        }

        //创建送货单
        DeliveryOrderDO order = new DeliveryOrderDO(loginUser.getMemberId(),loginUser.getMemberRoleId(),loginUser.getCompany());
        order.setDeliveryNo(createOrderSn(BaseDeliveryEnum.DELIVERY_ORDER_SERIAL_NO.getName()));
        order.setCreateTime(LocalDateTime.now());
        convertDeliveryOrderDO(order,param,type);
        deliveryOrderRepository.save(order);

        //物料信息
        List<DeliveryOrderProductDO> collect = convertDeliveryOrderProductDOList(param, order);
        deliveryOrderProductRepository.saveAll(collect);

        //来源送货计划、送货通知
        updateRelationOrder(loginUser,order,DeliveryOrderOuterStatusEnum.ALREADY_SUBMIT);

        //更新订单发送数量
        List<ProductReceiveOrDeliveryVO> deliveryQuantityList = collect.stream().map(o -> {
            ProductReceiveOrDeliveryVO vo = new ProductReceiveOrDeliveryVO();
            vo.setQuantity(o.getDeliveryCount());
            vo.setOrderProductId(o.getOrderProductId());
            return vo;
        }).collect(Collectors.toList());
        Wrapper<Void> orderWrapper = baseOrderDeliveryService.checkCreateVendorDelivery(loginUser, order, deliveryQuantityList);
        if(orderWrapper.getCode()!=ResponseCode.SUCCESS.getCode()){
            log.warn("送货单:更新订单数量失败,input:{},result:{}", JSONUtil.toJsonStr(deliveryQuantityList),JSONUtil.toJsonStr(orderWrapper));
            throw new BusinessException(orderWrapper.getCode(),orderWrapper.getMessage());
        }
        //更新送货计划数量
        deliveryPlanService.updateDeliveryPlanOrder(collect.stream().map(DeliveryOrderProductDO::getOrderProductId).collect(Collectors.toList()));

        //流转记录
        historyService.saveVendorOuterHistoryByDeliveryOrder(loginUser.getMemberId(),loginUser.getMemberRoleId(),loginUser.getUserName(), loginUser.getUserOrgName(),loginUser.getMemberRoleName(),order.getId(),order.getDeliveryNo(),DeliveryOperationEnum.CREATE_DELIVERY_ORDER, DeliveryOrderOuterStatusEnum.ALREADY_SUBMIT,param.getRemark(), DeliveryHistoryTypeEnum.DELIVERY_ORDER.getCode());
        return Wrapper.success();
    }


    @Override
    public Wrapper<DeliveryOrderDetailVO> detail(HttpHeaders headers, IdVO request) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        DeliveryOrderDO deliveryOrderDO = deliveryOrderRepository.findById(request.getId()).orElse(null);
        if(deliveryOrderDO==null){
            return Wrapper.fail(ResponseCode.ORDER_DELIVERY_ORDER_DOES_NOT_EXIST);
        }
        //数据权限校验
        if(!isMemberData(loginUser,deliveryOrderDO)){
            return Wrapper.fail(ResponseCode.DATA_AUTH_NOT_ALLOWED);
        }
        DeliveryOrderDetailVO response=new DeliveryOrderDetailVO();
        BeanUtils.copyProperties(deliveryOrderDO,response);
        response.setDeliverVO(convertLogisticsAddressVO(deliveryOrderDO.getDeliverBO()));
        response.setReceiverBO(convertLogisticsAddressVO(deliveryOrderDO.getReceiverBO()));
        response.setExecutorVO(convertLogisticsAddressVO(deliveryOrderDO.getExecutorBO()));
        response.setDeliveryTime(DateTimeUtil.formatDate(deliveryOrderDO.getDeliveryTime()));
        response.setSendTime(DateTimeUtil.formatMinuteTime(deliveryOrderDO.getSendTime()));
        response.setOuterStatusName(DeliveryOrderOuterStatusEnum.getNameByCode(deliveryOrderDO.getOuterStatus()));
        //外部流转记录
        response.setOuterHistoryList(historyService.listDeliveryOuterHistory(deliveryOrderDO.getId(), DeliveryHistoryTypeEnum.DELIVERY_ORDER.getCode()));
        return Wrapper.success(response);
    }

    @Transactional
    @Override
    public Wrapper<Void> update(HttpHeaders headers, DeliveryOrderUpdateVO request) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        DeliveryOrderDO order = deliveryOrderRepository.findById(request.getId()).orElse(null);
        if(order==null){
            return Wrapper.fail(ResponseCode.ORDER_DELIVERY_ORDER_DOES_NOT_EXIST);
        }else if(!isCreator(loginUser,order)){
            return Wrapper.fail(ResponseCode.DATA_AUTH_NOT_ALLOWED);
        }else if(!DeliveryOrderOuterStatusEnum.ALREADY_SUBMIT.getCode().equals(order.getOuterStatus())){
            return Wrapper.fail(ResponseCode.ORDER_DELIVERY_ORDER_UPDATE_STATUS_ERROR);
        }
        //送货单覆盖
        convertDeliveryOrderDOByUpdate(order,request);
        deliveryOrderRepository.saveAndFlush(order);

        /*修改时，不能修改明细数据
        //删除历史物料
        deliveryOrderProductRepository.deleteByDeliveryOrder(order);
        //物料信息
        deliveryOrderProductRepository.saveAll(convertDeliveryOrderProductDOList(request, order));
        */
        //无需更新订单发送数量，

        //流转记录
        historyService.saveVendorOuterHistoryByDeliveryOrder(loginUser.getMemberId(),loginUser.getMemberRoleId(),loginUser.getUserName(), loginUser.getUserOrgName(),loginUser.getMemberRoleName(),order.getId(),order.getDeliveryNo(),DeliveryOperationEnum.MODIFY_DELIVERY_ORDER, DeliveryOrderOuterStatusEnum.ALREADY_SUBMIT,request.getRemark(), DeliveryHistoryTypeEnum.DELIVERY_ORDER.getCode());
        return Wrapper.success();
    }

    @Transactional
    @Override
    public Wrapper<Void> invalid(HttpHeaders headers, InvalidVO request) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        DeliveryOrderDO order = deliveryOrderRepository.findById(request.getId()).orElse(null);
        if(order==null){
            return Wrapper.fail(ResponseCode.ORDER_DELIVERY_ORDER_DOES_NOT_EXIST);
        }else if(!isCreator(loginUser,order)){
            return Wrapper.fail(ResponseCode.DATA_AUTH_NOT_ALLOWED);
        }else if(!DeliveryOrderOuterStatusEnum.ALREADY_SUBMIT.getCode().equals(order.getOuterStatus())){
            return Wrapper.fail(ResponseCode.ORDER_DELIVERY_ORDER_INVALID_STATUS_ERROR);
        }
        order.setOuterStatus(DeliveryOrderOuterStatusEnum.INVALID.getCode());
        order.setUpdateTime(LocalDateTime.now());
        deliveryOrderRepository.saveAndFlush(order);

        //来源送货计划、送货通知
        updateRelationOrder(loginUser,order,DeliveryOrderOuterStatusEnum.INVALID);

        //TODO 更新订单发送数量

        //流转记录
        historyService.saveVendorOuterHistoryByDeliveryOrder(loginUser.getMemberId(),loginUser.getMemberRoleId(),loginUser.getUserName(), loginUser.getUserOrgName(),loginUser.getMemberRoleName(),order.getId(),order.getDeliveryNo(),DeliveryOperationEnum.INVALID_NOTICE_ORDER, DeliveryOrderOuterStatusEnum.INVALID,request.getRemark(), DeliveryHistoryTypeEnum.DELIVERY_ORDER.getCode());
        return Wrapper.success();
    }

    @Override
    public List<DeliveryOrderProductDO> getProductList(Long deliveryOrderId, List<Long> orderProductIdList) {
        if(deliveryOrderId==null||CollectionUtil.isEmpty(orderProductIdList)){
            return null;
        }
        DeliveryOrderDO orderDO=new DeliveryOrderDO();
        orderDO.setId(deliveryOrderId);
        List<DeliveryOrderProductDO> productDOS = deliveryOrderProductRepository.findByDeliveryOrderAndIdIn(orderDO, orderProductIdList);
        if(CollectionUtil.isNotEmpty(productDOS)){
            return productDOS;
        }
        return null;
    }

    @Override
    public DeliveryOrderDO getDeliveryOrderDO(Long id) {
        return deliveryOrderRepository.findById(id).orElse(null);
    }

    @Override
    public Wrapper<PageData<DeliveryOrderQueryVO>> pageByBuyer(HttpHeaders headers, DeliveryOrderPageVO deliveryDateVO) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        return Wrapper.success(pageBase(null,new MemberAndRoleIdDTO(loginUser.getMemberId(),loginUser.getMemberRoleId()),deliveryDateVO,null));
    }

    @Override
    public void updateStatus(UserLoginCacheDTO loginUser,Long deliveryOrderId,Integer status) {
        DeliveryOrderDO order = deliveryOrderRepository.findById(deliveryOrderId).orElse(null);
        if(order!=null&&!order.getOuterStatus().equals(status)){
            order.setOuterStatus(status);
            order.setUpdateTime(LocalDateTime.now());
            deliveryOrderRepository.saveAndFlush(order);
            if(DeliveryOrderOuterStatusEnum.RECEIVED.getCode().equals(status)) {
                //采购商生成收货单，变更发货单为已收货
                //流转记录
                historyService.saveVendorOuterHistoryByDeliveryOrder(loginUser.getMemberId(), loginUser.getMemberRoleId(), loginUser.getUserName(), loginUser.getUserOrgName(), loginUser.getMemberRoleName(), order.getId(), order.getDeliveryNo(), DeliveryOperationEnum.CREATE_RECEIVE_ORDER, DeliveryOrderOuterStatusEnum.RECEIVED, "", DeliveryHistoryTypeEnum.DELIVERY_ORDER.getCode());
            }else if(DeliveryOrderOuterStatusEnum.ALREADY_SUBMIT.getCode().equals(status)){
                //采购会员作废收货单，只需更新发货单状态，不用记录日志
            }
        }
    }
}
